package main

import "fmt"

type Component interface {
	Operation()
	Add(Component)
	Remove(Component)
	GetChild(int) Component
}

type Leaf struct {
	name string
}

func (l *Leaf) Operation() {
	fmt.Println("Leaf: ", l.name)
}

func (l *Leaf) Add(Component) {
	fmt.Println("Cannot add to a leaf")
}

func (l *Leaf) Remove(Component) {
	fmt.Println("Cannot remove from a leaf")
}

func (l *Leaf) GetChild(int) Component {
	return nil
}

type Composite struct {
	name     string
	Children []Component
}

func (c *Composite) Operation() {
	fmt.Println("Composite: ", c.name)
	for _, child := range c.Children {
		child.Operation()
	}
}

func (c *Composite) Add(component Component) {
	c.Children = append(c.Children, component)
}

func (c *Composite) Remove(component Component) {
	for i, child := range c.Children {
		if child == component {
			c.Children = append(c.Children[:i], c.Children[i+1:]...)
			break
		}
	}
}

func (c *Composite) GetChild(i int) Component {
	if i < 0 || i >= len(c.Children) {
		return nil
	}
	return c.Children[i]
}

func main() {
	leafA := &Leaf{name: "A"}
	leafB := &Leaf{name: "B"}

	composite := &Composite{name: "Composite Root"}
	composite.Add(leafA)
	composite.Add(leafB)

	composite.Operation()

	// Output:
	// Composite:  Composite Root
	// Leaf:  A
	// Leaf:  B
}
